package cn.initcap.algorithm.swing.sort.selection;

import cn.initcap.algorithm.swing.AlgoVisHelper;
import cn.initcap.algorithm.swing.BaseAlgoFrame;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;

/**
 * @author initcap
 * @date 8/1/19 12:05 PM
 */
public class AlgoVisualizer {

    private static int DELAY = 20;
    private SelectionSortData data;
    private BaseAlgoFrame frame;

    public AlgoVisualizer(int sceneWidth, int sceneHeight, int n) {

        data = new SelectionSortData(n, sceneHeight);

        // 初始化视图
        EventQueue.invokeLater(() -> {
            frame = new BaseAlgoFrame("Selection Sort Visualization", sceneWidth, sceneHeight) {
                @Override
                public void draw(Graphics graphics) {
                    Graphics2D g2d = (Graphics2D) graphics;
                    int w = sceneWidth / data.N();
                    for (int i = 0; i < data.N(); i++) {
                        if (i < data.orderedIndex) {
                            AlgoVisHelper.setColor(g2d, AlgoVisHelper.RED);
                        } else {
                            AlgoVisHelper.setColor(g2d, AlgoVisHelper.GREY);
                        }

                        if (i == data.currentCompareIndex) {
                            AlgoVisHelper.setColor(g2d, AlgoVisHelper.LIGHT_BLUE);
                        }
                        if (i == data.currentMinIndex) {
                            AlgoVisHelper.setColor(g2d, AlgoVisHelper.INDIGO);
                        }
                        AlgoVisHelper.fillRectangle(g2d, i * w, sceneHeight - data.get(i), w - 1, data.get(i));
                    }
                }
            };
            new Thread(() -> {
                run();
            }).start();
        });
    }

    public static void main(String[] args) {

        int sceneWidth = 800;
        int sceneHeight = 800;
        int n = 100;

        new AlgoVisualizer(sceneWidth, sceneHeight, n);
    }

    private void run() {

        setData(0, -1, -1);

        for (int i = 0; i < data.N(); i++) {
            // 寻找[i, n)区间里的最小值的索引
            int minIndex = i;
            setData(i, -1, minIndex);

            for (int j = i + 1; j < data.N(); j++) {
                setData(i, j, minIndex);

                if (data.get(j) < data.get(minIndex)) {
                    minIndex = j;
                    setData(i, j, minIndex);
                }
            }

            data.swap(i, minIndex);
            setData(i + 1, -1, -1);
        }

        setData(data.N(), -1, -1);
    }

    private void setData(int orderedIndex, int currentCompareIndex, int currentMinIndex) {
        data.orderedIndex = orderedIndex;
        data.currentCompareIndex = currentCompareIndex;
        data.currentMinIndex = currentMinIndex;

        frame.render(data);
        AlgoVisHelper.pause(DELAY);
    }
}